"""
声明式中间件 - 配置即代码
基于Linus设计哲学："好代码没有特殊情况"
"""

import time
import inspect
from typing import Callable, List
from .logger import get_default_logger


class Middleware:
    """声明式中间件 - 配置即代码"""
    
    def __init__(self):
        self.before_hooks: List[Callable] = []
        self.after_hooks: List[Callable] = []
        self.error_hooks: List[Callable] = []
        self.conditions: List[Callable] = []
    
    def before(self, func: Callable):
        """添加前置钩子"""
        self.before_hooks.append(func)
        return self
    
    def after(self, func: Callable):
        """添加后置钩子"""
        self.after_hooks.append(func)
        return self
    
    def on_error(self, func: Callable):
        """添加错误钩子"""
        self.error_hooks.append(func)
        return self
    
    def when(self, condition: Callable):
        """添加条件判断"""
        self.conditions.append(condition)
        return self
    
    def build(self):
        """构建中间件函数"""
        def middleware_func(handler: Callable):
            setattr(middleware_func, "is_middleware", True)
            
            async def wrapper(scope, receive, send):
                # 创建上下文
                context = {
                    "scope": scope,
                    "receive": receive,
                    "send": send,
                    "handler": handler
                }
                
                # 检查条件
                for condition in self.conditions:
                    if not condition(context):
                        return await handler(scope, receive, send)
                
                try:
                    # 执行前置钩子
                    for hook in self.before_hooks:
                        await self._call_hook(hook, context)
                    
                    # 执行处理器
                    result = await handler(scope, receive, send)
                    context["result"] = result
                    
                    # 检查是否为流式响应，避免阻塞流式传输
                    is_streaming = (
                        hasattr(result, 'content_generator') or
                        (hasattr(result, '__class__') and
                         result.__class__.__name__ in ('StreamResponse', 'SSEResponse'))
                    )
                    
                    if not is_streaming:
                        # 非流式响应：执行后置钩子
                        for hook in self.after_hooks:
                            await self._call_hook(hook, context)
                    
                    return result
                    
                except Exception as e:
                    context["error"] = e
                    
                    # 执行错误钩子
                    for hook in self.error_hooks:
                        try:
                            await self._call_hook(hook, context)
                        except Exception:
                            # 错误钩子本身出错，继续传播原异常
                            pass
                    
                    # 重新抛出原异常
                    raise
            
            return wrapper
        
        return middleware_func
    
    async def _call_hook(self, hook: Callable, context: dict):
        """调用钩子函数"""
        # 检查钩子函数的签名
        sig = inspect.signature(hook)
        params = list(sig.parameters.keys())
        
        if len(params) == 0:
            # 无参数钩子
            if inspect.iscoroutinefunction(hook):
                await hook()
            else:
                hook()
        elif len(params) == 1:
            # 单参数钩子，传递上下文
            if inspect.iscoroutinefunction(hook):
                await hook(context)
            else:
                hook(context)
        else:
            # 多参数钩子，尝试智能匹配
            kwargs = {}
            for param in params:
                if param in context:
                    kwargs[param] = context[param]
            
            if inspect.iscoroutinefunction(hook):
                await hook(**kwargs)
            else:
                hook(**kwargs)


# 装饰器函数 - 保持向后兼容
def middleware(func: Callable) -> Callable:
    """简单中间件装饰器 - 保持向后兼容"""
    setattr(func, "is_middleware", True)
    return func


# 预定义中间件组件
def cors(origins="*", methods="GET,POST,PUT,DELETE,OPTIONS", headers="*"):
    """CORS中间件"""
    def add_cors_headers(context):
        result = context.get("result")
        if hasattr(result, "headers"):
            result.headers.setdefault("Access-Control-Allow-Origin", origins)
            result.headers.setdefault("Access-Control-Allow-Methods", methods)
            result.headers.setdefault("Access-Control-Allow-Headers", headers)
    
    def preflight_handler(context):
        """处理预检请求"""
        scope = context["scope"]
        if scope.get("method") == "OPTIONS":
            # 直接返回预检响应，不调用处理器
            from gua import respond
            return respond("", status=200, headers={
                "Access-Control-Allow-Origin": origins,
                "Access-Control-Allow-Methods": methods,
                "Access-Control-Allow-Headers": headers,
                "Access-Control-Max-Age": "86400"
            })
        return None
    
    return Middleware().before(preflight_handler).after(add_cors_headers).build()


def auth(public_paths=None, header="authorization", auth_func=None):
    """认证中间件 - 默认保护所有路径，只列出公开路径"""
    if public_paths is None:
        public_paths = []  # 默认空列表，即所有路径都需要认证
    
    def check_auth(context):
        scope = context["scope"]
        path = scope["path"]
        
        # 检查是否为公开路径
        if any(path.startswith(p) for p in public_paths):
            return  # 公开路径，直接通过
        
        # 所有其他路径都需要认证
        headers = dict(scope.get("headers", []))
        auth_header = headers.get(header.encode(), b"").decode()
        
        if auth_func:
            # 使用自定义认证函数
            if not auth_func(auth_header):
                raise Exception("Unauthorized")
        else:
            # 默认Bearer Token认证
            if not auth_header.startswith("Bearer "):
                raise Exception("Unauthorized")
    
    return Middleware().before(check_auth).build()


def logging(format_str="Request: {method} {path}"):
    """日志中间件"""
    def log_request(context):
        scope = context["scope"]
        method = scope.get("method", "WS")
        path = scope["path"]
        logger = get_default_logger()
        logger.info(
            "middleware_builder_request_received",
            message=f"请求经过声明式日志中间件: {format_str.format(method=method, path=path)}",
            method=method,
            path=path,
            client_ip=scope.get('client', ['unknown'])[0] if scope.get('client') else 'unknown'
        )
    
    return Middleware().before(log_request).build()


def rate_limit(max_requests=100, window_seconds=60, key_func=None):
    """限流中间件"""
    requests = {}
    
    def default_key_func(context):
        scope = context["scope"]
        return scope.get("client", ["unknown"])[0]
    
    if key_func is None:
        key_func = default_key_func
    
    def check_rate_limit(context):
        nonlocal requests
        key = key_func(context)
        current_time = time.time()
        
        if key not in requests:
            requests[key] = []
        
        # 清理过期请求
        requests[key] = [req_time for req_time in requests[key] 
                        if current_time - req_time < window_seconds]
        
        # 检查是否超过限制
        if len(requests[key]) >= max_requests:
            raise Exception("Rate limit exceeded")
        
        # 记录当前请求
        requests[key].append(current_time)
    
    return Middleware().before(check_rate_limit).build()

